#!/bin/env python

import socket
import sys


class DNSReply:
    def __init__(self, data):
        self.data = data
        self.domain = ''

        opcode = (ord(data[2]) >> 3) & 15  # Opcode bits
        if opcode == 0:  # Standard query
            ind = 12
            len = ord(data[ind])
            while len != 0:
                self.domain += data[ind + 1:ind + len + 1] + '.'
                ind += len + 1
                len = ord(data[ind])

    def response(self, ip):
        packet = ''
        if self.domain:
            packet += self.data[:2] + "\x81\x80" # Transaction ID and Flags
            packet += self.data[4:6] + self.data[4:6] + '\x00\x00\x00\x00'  # Questions and Answers Counts
            packet += self.data[12:]  # Original Domain Name Question
            packet += '\xc0\x0c'  # Pointer to domain name
            packet += '\x00\x01\x00\x01\x00\x00\x00\x3c\x00\x04'  # Response type, ttl and resource data length -> 4 bytes
            packet += str.join('', map(lambda x: chr(int(x)), ip.split('.')))  # 4bytes of IP
        return packet


if __name__ == '__main__':
    if len(sys.argv) < 2:
        print "Usage: %s ip" % sys.argv[0]
        sys.exit(0)

    ip = sys.argv[1]
    print 'pyminifakeDNS:: dom.query. 60 IN A %s' % ip

    udps = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    udps.bind(('', 53))

    try:
        while 1:
            data, addr = udps.recvfrom(1024)
            r = DNSReply(data)
            udps.sendto(r.response(ip), addr)
            print 'Reply: %s -> %s' % (r.domain[:-1], ip)
    except KeyboardInterrupt:
        print 'Finish.'
        udps.close()
